import { toast } from 'sonner';
import { 
  AgentRunLimitError, 
  ProjectLimitError, 
  BillingError,
  TriggerLimitError,
  ModelAccessDeniedError,
  CustomWorkerLimitError,
  ThreadLimitError,
  AgentCountLimitError
} from './api/errors';
import { usePricingModalStore } from '@/stores/pricing-modal-store';

export interface ApiError extends Error {
  status?: number;
  code?: string;
  details?: any;
  response?: Response;
}

export interface ErrorContext {
  operation?: string;
  resource?: string;
  silent?: boolean;
}

const getStatusMessage = (status: number): string => {
  switch (status) {
    case 400:
      return 'Invalid request. Please check your input and try again.';
    case 401:
      return 'Authentication required. Please sign in again.';
    case 403:
      return 'Access denied. You don\'t have permission to perform this action.';
    case 404:
      return 'The requested resource was not found.';
    case 408:
      return 'Request timeout. Please try again.';
    case 409:
      return 'Conflict detected. The resource may have been modified by another user.';
    case 422:
      return 'Invalid data provided. Please check your input.';
    case 429:
      return 'Too many requests. Please wait a moment and try again.';
    case 500:
      return 'Server error. Our team has been notified.';
    case 502:
      return 'Service temporarily unavailable. Please try again in a moment.';
    case 503:
      return 'Service maintenance in progress. Please try again later.';
    case 504:
      return 'Request timeout. The server took too long to respond.';
    default:
      return 'An unexpected error occurred. Please try again.';
  }
};

const extractErrorMessage = (error: any): string => {
  if (error instanceof BillingError) {
    return error.detail?.message || error.message || 'Billing issue detected';
  }

  if (error instanceof AgentRunLimitError) {
    return error.detail?.message || error.message || 'Agent run limit exceeded';
  }

  if (error instanceof ProjectLimitError) {
    return error.detail?.message || error.message || 'Project limit exceeded';
  }

  if (error instanceof AgentCountLimitError) {
    return error.detail?.message || error.message || 'Agent limit exceeded';
  }

  if (error instanceof TriggerLimitError) {
    return error.detail?.message || error.message || 'Trigger limit exceeded';
  }

  if (error instanceof ModelAccessDeniedError) {
    return error.detail?.message || error.message || 'Model access denied';
  }

  if (error instanceof CustomWorkerLimitError) {
    return error.detail?.message || error.message || 'Custom worker limit exceeded';
  }

  if (error instanceof ThreadLimitError) {
    return error.detail?.message || error.message || 'Thread limit exceeded';
  }

  if (error instanceof Error) {
    return error.message;
  }

  if (error?.response) {
    const status = error.response.status;
    return getStatusMessage(status);
  }

  if (error?.status) {
    return getStatusMessage(error.status);
  }

  if (typeof error === 'string') {
    return error;
  }

  if (error?.message) {
    return error.message;
  }

  if (error?.error) {
    return typeof error.error === 'string' ? error.error : error.error.message || 'Unknown error';
  }

  return 'An unexpected error occurred';
};

const shouldShowError = (error: any, context?: ErrorContext): boolean => {
  if (context?.silent) {
    return false;
  }
  if (error instanceof BillingError) {
    return false;
  }

  if (error?.status === 404 && context?.resource) {
    return false;
  }

  return true;
};

const formatErrorMessage = (message: string, context?: ErrorContext): string => {
  if (!context?.operation && !context?.resource) {
    return message;
  }

  const parts = [];
  
  if (context.operation) {
    parts.push(`Failed to ${context.operation}`);
  }
  
  if (context.resource) {
    parts.push(context.resource);
  }

  const prefix = parts.join(' ');
  
  if (message.toLowerCase().includes(context.operation?.toLowerCase() || '')) {
    return message;
  }

  return `${prefix}: ${message}`;
};


export const handleApiError = (error: any, context?: ErrorContext): void => {
  console.error('API Error:', error, context);

  if (!shouldShowError(error, context)) {
    return;
  }

  const rawMessage = extractErrorMessage(error);
  const formattedMessage = formatErrorMessage(rawMessage, context);

  if (error instanceof AgentRunLimitError) {
    // Note: Translations should be handled in components that use this handler
    // This is a fallback for non-component contexts
    const upgradeMessage = `You've reached your limits. Agent Run Limit (${error.detail.running_count}/${error.detail.limit})`;
    usePricingModalStore.getState().openPricingModal({ isAlert: true, alertTitle: upgradeMessage });
    return;
  }

  if (error instanceof ProjectLimitError) {
    // Note: Translations should be handled in components that use this handler
    // This is a fallback for non-component contexts
    const upgradeMessage = `You've reached your limits. Project Limit (${error.detail.current_count}/${error.detail.limit})`;
    usePricingModalStore.getState().openPricingModal({ isAlert: true, alertTitle: upgradeMessage });
    return;
  }

  if (error instanceof ThreadLimitError) {
    const upgradeMessage = `You've reached your limits. Thread Limit (${error.detail.current_count}/${error.detail.limit})`;
    usePricingModalStore.getState().openPricingModal({ isAlert: true, alertTitle: upgradeMessage });
    return;
  }

  if (error instanceof AgentCountLimitError) {
    const upgradeMessage = `You've reached your limits. Worker Limit (${error.detail.current_count}/${error.detail.limit})`;
    usePricingModalStore.getState().openPricingModal({ isAlert: true, alertTitle: upgradeMessage });
    return;
  }

  if (error instanceof TriggerLimitError) {
    const upgradeMessage = `You've reached your limits. Trigger Limit (${error.detail.current_count}/${error.detail.limit})`;
    usePricingModalStore.getState().openPricingModal({ isAlert: true, alertTitle: upgradeMessage });
    return;
  }

  if (error instanceof ModelAccessDeniedError) {
    const upgradeMessage = 'Upgrade to access premium AI models';
    usePricingModalStore.getState().openPricingModal({ isAlert: true, alertTitle: upgradeMessage });
    return;
  }

  if (error instanceof CustomWorkerLimitError) {
    const upgradeMessage = `You've reached your limits. Worker Limit (${error.detail.current_count}/${error.detail.limit})`;
    usePricingModalStore.getState().openPricingModal({ isAlert: true, alertTitle: upgradeMessage });
    return;
  }

  if (error instanceof BillingError) {
    // Extract billing error message and determine if credits are exhausted
    const message = error.detail?.message?.toLowerCase() || '';
    const originalMessage = error.detail?.message || '';
    const isCreditsExhausted = 
      message.includes('credit') ||
      message.includes('balance') ||
      message.includes('insufficient') ||
      message.includes('out of credits') ||
      message.includes('no credits');
    
    // Try to extract balance from message (e.g., "Your balance is -284 credits")
    const balanceMatch = originalMessage.match(/balance is (-?\d+)\s*credits/i);
    const balance = balanceMatch ? balanceMatch[1] : null;
    
    // Open pricing modal with appropriate alert title and subtitle
    const alertTitle = isCreditsExhausted 
      ? 'You ran out of credits'
      : 'Billing check failed';
    
    const alertSubtitle = balance 
      ? `Your current balance is ${balance} credits. Upgrade your plan to continue.`
      : isCreditsExhausted 
        ? 'Upgrade your plan to get more credits and continue using the AI assistant.'
        : 'Please upgrade to continue.';
    
    usePricingModalStore.getState().openPricingModal({ 
      isAlert: true, 
      alertTitle,
      alertSubtitle
    });
    return;
  }

  if (error?.status >= 500) {
    toast.error(formattedMessage, {
      description: 'Our team has been notified and is working on a fix.',
      duration: 6000,
    });
  } else if (error?.status === 403) {
    toast.error(formattedMessage, {
      description: 'Contact support if you believe this is an error.',
      duration: 6000,
    });
  } else if (error?.status === 429) {
    toast.warning(formattedMessage, {
      description: 'Please wait a moment before trying again.',
      duration: 5000,
    });
  } else {
    toast.error(formattedMessage, {
      duration: 5000,
    });
  }
};

export const handleNetworkError = (error: any, context?: ErrorContext): void => {
  const isNetworkError = 
    error?.message?.includes('fetch') ||
    error?.message?.includes('network') ||
    error?.message?.includes('connection') ||
    error?.code === 'NETWORK_ERROR' ||
    !navigator.onLine;

  if (isNetworkError) {
    toast.error('Connection error', {
      description: 'Please check your internet connection and try again.',
      duration: 6000,
    });
  } else {
    handleApiError(error, context);
  }
};

export const handleApiSuccess = (message: string, description?: string): void => {
  toast.success(message, {
    description,
    duration: 3000,
  });
};

export const handleApiWarning = (message: string, description?: string): void => {
  toast.warning(message, {
    description,
    duration: 4000,
  });
};

export const handleApiInfo = (message: string, description?: string): void => {
  toast.info(message, {
    description,
    duration: 3000,
  });
};

/**
 * Check if an error is a billing/limit error that should open the pricing modal
 */
export const isBillingError = (error: any): boolean => {
  return (
    error instanceof BillingError ||
    error instanceof AgentRunLimitError ||
    error instanceof ProjectLimitError ||
    error instanceof ThreadLimitError ||
    error instanceof AgentCountLimitError ||
    error instanceof TriggerLimitError ||
    error instanceof ModelAccessDeniedError ||
    error instanceof CustomWorkerLimitError
  );
};

/**
 * Handle billing errors by opening the pricing modal with appropriate message.
 * Returns true if error was handled, false otherwise.
 * Use this in mutation onError callbacks.
 */
export const handleBillingError = (error: any): boolean => {
  if (!isBillingError(error)) {
    return false;
  }
  
  handleApiError(error);
  return true;
}; 